import axios from 'axios'
import {ElLoading, ElMessage } from 'element-plus'
import {alertErrorMsg, isDebugMode, isNullOrUndefined, svc} from './common'

import {getApplication, getToken, getUserId, getH5Application, getH5Token, getH5UserId, getH5Id} from '@/config/cookie'
import useUserStore from "@/store/modules/user";

const newLine = '<br />'

const service = axios.create({
    baseURL: window.location.origin + '/api/v1',
    // 超时时间 单位是ms，这里设置了30s的超时时间
    timeout: 30 * 1000,
})

export function apiUrl(svc) {
    let v = 'v1'
    let service = svc ? '/' + svc : ''
    return window.location.origin + service + `/api/${v}`
}

// 请求拦截器
service.interceptors.request.use(config => {
    if (config.isFullscreen) {
        config.fullElLoging = ElLoading.service({fullscreen: true})
    }
    config.baseURL = config.url
    let contentType = config.headers['Content-Type']
    console.debug('config', config)
    console.debug('config.headers', config.headers)
    console.debug('Content-Type', contentType)
    if (contentType && !contentType.startsWith('multipart/form-data')) {
        config.headers['Content-Type'] = 'application/json'
        config.data = JSON.stringify(config.data)
    }
    config.headers['application'] = 'admin'
    const H5Id = getH5Id()
    const token = H5Id ? getH5Token() : getToken()
    token && (config.headers.token = token)
    const userId = H5Id ? getH5UserId() : getUserId()
    userId && (config.headers.userId = userId)
    const application = H5Id ? getH5Application() : getApplication()
    application && (config.headers.application = application)
    return config
}, error => {
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(({data: {code, data, message, requestId, duration, debug} = {}, config}) => {
    if (config)
        config.fullElLoging?.close()
    if (code === '000') {
        return Promise.resolve(data)
    }
    if (code === '998') {
        // 跳转到登录页面，将token从cookie中删除
        let r = useUserStore().logout()
        console.debug('logout', r)
        window.location.href = '/login'
    }
    if (isNullOrUndefined(code))
        code = ''
    if (!message)
        message = '未知错误！'
    if (isNullOrUndefined(requestId))
        requestId = ''
    let msg = '【错误】' + code + ':' + message + newLine + '【请求】' + requestId
    if (isDebugMode()) {
        msg = msg + newLine + '【耗时】' + duration + '毫秒'
        if (isDebugMode()) {
            msg = msg + newLine + '异常：' + debug
        }
    }
    alertErrorMsg(msg)
    return Promise.reject({code, message})
}, error => {
    if (error.config) {
        error.config.fullElLoging?.close()
    }
    // 异常处理
    if (error && error.response) {
        let msg
        switch (error.response.status) {
            case 400:
                msg = '[错误请求]'
                break
            case 401:
                msg = '[未授权，请重新登录]'
                break
            case 403:
                alertErrorMsg('[拒绝访问]')
                return Promise.reject(error.response)
            case 404: {
                alertErrorMsg('[请求错误，未找到该资源]')
                return Promise.reject(error.response)
            }
            case 405:
                alertErrorMsg('[请求方法未允许]')
                return Promise.reject(error.response)
            case 408:
                msg = '[请求超时]'
                break
            case 500:
                msg = '[接口调用错误]'
                break
            case 501:
                msg = '[网络未实现]'
                break
            case 502:
                msg = '[网关错误]'
                break
            case 503:
                msg = '[服务不可用]'
                break
            case 504:
                msg = '[网络超时]'
                break
            case 505:
                msg = '[http版本不支持该请求]'
                break
            default:
                msg = `[连接错误，状态码:${error.response.status}]`
        }
        if (error.response.data.code !== undefined) {
            msg = '【错误】' + error.response.data.code + ':' + error.response.data.message + newLine + '【请求】' + error.response.data.requestId
            if (isDebugMode()) {
                msg = msg + newLine + '【耗时】' + error.response.data.duration + '毫秒'
                if (isDebugMode()) {
                    msg = msg + newLine + '异常：' + error.response.data.debug
                }
            }
        } else {
            msg = '【错误】' + error.response.status + ':' + error.response.statusText
        }
        alertErrorMsg(msg)
    } else {
        let msg
        if (JSON.stringify(error).includes('timeout')) {
            msg = '[服务器响应超时]'
        } else {
            msg = '[网络错误]'
        }
        alertErrorMsg(msg)
    }
    return Promise.reject(error.response)
})

export function exec(method, svc, uri, data, isFullscreen) {
    const config = {
        isFullscreen,
        method: method,
        url: apiUrl(svc) + uri
    }
    if (data) {
        for (const dataKey in data) {
            if (dataKey === 'createBy' || dataKey === 'updateBy') {
                delete data[dataKey]
            }
            if (isNullOrUndefined(data[dataKey])) {
                data[dataKey] = ''
            }
        }
        config.data = data
    }
    return service(config)
}

export function doGet(svc, url, params, isFullscreen = true) {
    let str = ''
    if (params) {
        for (const key in params) {
            if (isNullOrUndefined(params[key])) {
                params[key] = ''
            }
            if (str === '') {
                str = key + '=' + params[key]
            } else {
                let paramsValue = params[key]
                if (typeof paramsValue == 'string') {
                    paramsValue = encodeURI(params[key])
                }
                str = str + '&' + key + '=' + paramsValue
            }
        }
    }
    if (str !== '') {
        str = "?" + str
    }
    return exec('get', svc, url + str, null, isFullscreen)
}

export function doPost(svc, url, data, isFullscreen = true) {
    return exec('post', svc, url, data, isFullscreen)
}

export function doPut(svc, url, data, isFullscreen = true) {
    return exec('put', svc, url, data, isFullscreen)
}

export function doDelete(svc, url, data, isFullscreen = true) {
    return exec('delete', svc, url, data, isFullscreen)
}

export function doDownload(svc, url, params) {
    let str = ''
    for (const key in params) {
        if (str === '') {
            str = str + '?' + key + '=' + params[key]
        } else {
            str = str + '&' + key + '=' + params[key]
        }
    }
    window.location.href = apiUrl(svc) + url + str
}

export function doUpload(svc, url, param) {
    const config = {
        isFullscreen: true,
        method: 'post',
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        url: apiUrl(svc) + url,
        data: param,
    }
    return service(config)
}

export function fillUser(list, arr1, arr2) {
    let set = new Set();
    list && list.length > 0 && list.map((value) => {
        arr1 && arr1.length > 0 && arr1.map((val) => {
            if (value[val]) {
                set.add(value[val])
            }
        })
    })
    if (!set || set.size === 0) {
        return false
    }
    let params = Array.from(set)
    doGet(svc, "/user/" + params.join(','), {}, false).then(res => {
        if (res?.length > 0) {
            let user = new Map()
            res.map(u => {
                user.set(String(u.id), u)
            })
            list.map((item) => {
                arr1.map((key, i) => {
                    item[arr2[i]] = user.get(item[key])?.name || ''
                })
            })
        }
    })
}

export function getFile(id, fileName) {
    let postDownloadLoading = ElLoading.service({fullscreen: true})
    axios({
        method:'get',
        url: '/' + svc + '/api/v1/customAttachment/download/' + id,
        responseType:'arraybuffer'
    }).then(data => {
        console.debug('dataCode',data)
        postDownloadLoading.close()
        const url = window.URL.createObjectURL(new Blob([data]));
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
    }).catch(error => {
        postDownloadLoading.close()
        ElMessage.error(error)
    });
}

function doExecDownload(method, svc, url, params, fileName) {
    let uri = url
    let body = ''
    if (method === 'GET') {
        let str = ''
        Object.keys(params).map(item => {
            if (params[item]){
                str += `&${item}=${params[item]}`
            }
        })
        if (str){
            str = str.replace('&','?')
        }
        uri = url + str
    }
    if (method === 'POST') {
        body = JSON.stringify(params)
    }
    let downloadLoading = ElLoading.service({fullscreen: true})
    const headers = {
        'Accept': 'application/json, */*',
        'Content-Type': 'application/json',
        'application': 'admin',
        'cache': 'default',
        'x-ajax': 'true',
    }
    const token = getToken()
    token && (headers.token = token)
    const userId = getUserId()
    userId && (headers.userId = userId)
    let init = {
        method,
        headers,
        'credentials': 'include', //表示请求是否携带cookie
    }
    if (method === 'POST') {
        init.body = body
    }
    return fetch(apiUrl(svc) + uri, init).then(function (response) {
        downloadLoading.close()
        if (response.ok) {
            response.blob().then((blob) => {
                const a = window.document.createElement('a');
                const downUrl = window.URL.createObjectURL(blob);// 获取 blob 本地文件连接 (blob 为纯二进制对象，不能够直接保存到磁盘上)
                let disposition = response.headers.get('Content-Disposition')
                let filename = disposition.split('filename=')[1] || fileName;
                if (filename.startsWith("'") || filename.startsWith('"')) {
                    filename = filename.substring(1)
                }
                if (filename.endsWith("'") || filename.endsWith('"')) {
                    filename = filename.substring(0, filename.length - 1)
                }
                a.href = downUrl;
                a.download = `${decodeURI(filename)}`;
                a.click();
                window.URL.revokeObjectURL(downUrl);
            });
            return {state: 1}
        } else {
            response.json().then(res => {
                if (res !== '000') {
                    alertErrorMsg(res.message)
                }
            })
            throw new Error('下载失败')
        }
    })
}

export function doPostDownload(svc, url, params, fileName) {
    return doExecDownload('POST', svc, url, params, fileName)
}

export function doGetDownload(svc, url, params, fileName) {
    return doExecDownload('GET', svc, url, params, fileName)
}
